﻿namespace EyeOpen.Mapping.SpecializedNhibernate
{
    using System;
    using System.Reflection;
    using System.Xml.Linq;
    using System.Collections.Generic;
    using EyeOpen.Mapping.Nhibernate;

    public class SpecializedNhibernateMapper : NhibernateMapper
    {
        public SpecializedNhibernateMapper() 
        { 
        }

        public SpecializedNhibernateMapper(string generatorTypeName) 
            : base(generatorTypeName) 
        { 
        }

        public override IDictionary<Type, XElement> GenerateMappings(Assembly assembly)
        {
            return base.GenerateMappings(assembly, type => this.IsUniqueObject(type));
        }

        protected override bool CanMapProperty(PropertyInfo property)
        {
            if ((property.PropertyType.Attributes & TypeAttributes.ClassSemanticsMask) == TypeAttributes.ClassSemanticsMask)
            {
                return false;
            }

            if (IsBaseType(property.PropertyType))
            {
                return true;
            }

            if (this.IsUniqueObject(property.PropertyType))
            {
                return true;
            }

            return false;
        }

        private bool IsUniqueObject(Type type)
        {
            Type uniqueObject = type.BaseType;

            bool isUniqueObject = false;
            bool canExit = false;
            do
            {
                canExit = (uniqueObject != null) && (uniqueObject.FullName != "System.Object");
                isUniqueObject = uniqueObject.Name == "UniqueObject";
                canExit = canExit | isUniqueObject;
                uniqueObject = uniqueObject.BaseType;
            }
            while (!canExit);

            return isUniqueObject;
        }
    }
}
